# 文件名: direct_run.py
import os
import sys
import asyncio
import socket
import webbrowser
import threading
import time
import logging
import shutil
from hypercorn.asyncio import serve
from hypercorn.config import Config
from sqlalchemy import text
from sqlalchemy.exc import OperationalError
from app.utils.logging_config import logger
# 导入系统托盘相关库
import pystray
from PIL import Image, ImageDraw

# 确保app/utils目录存在
os.makedirs(os.path.join("app", "utils"), exist_ok=True)

# 获取正确的应用路径
if getattr(sys, 'frozen', False):
    # 打包环境
    base_path = os.path.dirname(sys.executable)
    # 获取资源文件的路径（在打包环境中）
    resource_path = sys._MEIPASS
else:
    # 开发环境
    base_path = os.path.dirname(os.path.abspath(__file__))
    resource_path = base_path

# 设置工作目录
os.chdir(base_path)

# 添加日志目录
os.makedirs("logs", exist_ok=True)

# 导入日志配置
sys.path.append(base_path)

logger.info(f"设置工作目录: {base_path}")
logger.info(f"资源文件路径: {resource_path}")

# 创建必要的目录
os.makedirs("db", exist_ok=True)
os.makedirs(os.path.join("app", "static", "downloads"), exist_ok=True)
os.makedirs(os.path.join("app", "templates"), exist_ok=True)

# 复制资源文件到工作目录（仅在打包环境中）
if getattr(sys, 'frozen', False):
    # 复制模板文件
    source_templates = os.path.join(resource_path, "app", "templates")
    target_templates = os.path.join(base_path, "app", "templates")

    if os.path.exists(source_templates):
        logger.info(f"复制模板文件从 {source_templates} 到 {target_templates}")
        for item in os.listdir(source_templates):
            s = os.path.join(source_templates, item)
            d = os.path.join(target_templates, item)
            try:
                if os.path.isfile(s):
                    shutil.copy2(s, d)
                    logger.info(f"已复制文件: {item}")
            except Exception as e:
                logger.error(f"复制文件失败 {item}: {str(e)}")

    # 复制静态文件（如果需要）
    source_static = os.path.join(resource_path, "app", "static")
    target_static = os.path.join(base_path, "app", "static")

    if os.path.exists(source_static) and not os.path.exists(os.path.join(target_static, "css")):
        logger.info(f"复制静态文件从 {source_static} 到 {target_static}")
        try:
            # 使用dirs_exist_ok=True参数（Python 3.8+）
            # 对于较早的Python版本，需要先检查目录是否存在
            try:
                shutil.copytree(source_static, target_static, dirs_exist_ok=True)
            except TypeError:
                # Python 3.7 或更早版本
                for item in os.listdir(source_static):
                    s = os.path.join(source_static, item)
                    d = os.path.join(target_static, item)
                    if os.path.isdir(s):
                        if not os.path.exists(d):
                            shutil.copytree(s, d)
                    else:
                        shutil.copy2(s, d)
        except Exception as e:
            logger.error(f"复制静态文件失败: {str(e)}")

# 手动初始化数据库
try:
    logger.info("手动初始化数据库...")
    # 导入数据库模块
    from app.models.database import create_tables, Base, engine, SystemSetting, SessionLocal

    # 创建数据库表
    create_tables()
    logger.info("数据库表创建完成")

    # 初始化基本配置
    try:
        db = SessionLocal()
        logger.info("创建数据库会话成功")

        # 检查系统设置表是否存在
        try:
            db.execute(text("SELECT 1 FROM system_settings LIMIT 1"))
            logger.info("系统设置表已存在")
        except OperationalError:
            logger.info("系统设置表不存在，手动创建表...")
            Base.metadata.create_all(bind=engine)
            logger.info("数据库表手动创建完成")

        # 检查API令牌是否存在，不存在则创建
        api_token = ""
        try:
            setting = db.query(SystemSetting).filter(SystemSetting.key == "api_token").first()
            if not setting:
                logger.info("API令牌不存在，创建默认值...")
                setting = SystemSetting(
                    key="api_token",
                    value=api_token,
                    description="API访问令牌，用于调用TikTok/抖音/Instagram API"
                )
                db.add(setting)
                db.commit()
                logger.info("API令牌已设置")
            else:
                logger.info(f"API令牌已存在: {setting.value[:5]}...")
        except Exception as e:
            logger.error(f"检查API令牌时出错: {str(e)}")
            # 尝试强制创建表和设置
            try:
                Base.metadata.create_all(bind=engine)
                logger.info("强制创建数据库表")
                setting = SystemSetting(
                    key="api_token",
                    value=api_token,
                    description="API访问令牌，用于调用TikTok/抖音/Instagram API"
                )
                db.add(setting)
                db.commit()
                logger.info("强制设置API令牌成功")
            except Exception as e2:
                logger.error(f"强制创建表和设置时出错: {str(e2)}")

        # 关闭会话
        db.close()
    except Exception as e:
        logger.error(f"初始化基本配置时出错: {str(e)}")
except Exception as e:
    logger.error(f"初始化数据库时出错: {str(e)}")

# 导入应用
from app.main import app

# 全局变量，用于标记应用是否应该退出
should_exit = False
server_running = False


def open_browser():
    # 等待服务器启动
    time.sleep(2)
    webbrowser.open('http://localhost:8000')


# 创建系统托盘图标
def create_tray_icon():
    # 检查是否有图标文件
    icon_path = os.path.join(base_path, "app", "static", "icon.png")
    if not os.path.exists(icon_path):
        # 如果没有图标，创建一个简单的图标
        img = Image.new('RGBA', (64, 64), color=(0, 0, 0, 0))
        d = ImageDraw.Draw(img)
        d.rectangle((10, 10, 54, 54), fill=(73, 109, 137))
        d.rectangle((20, 20, 44, 44), fill=(255, 255, 255))

        # 确保目录存在
        os.makedirs(os.path.dirname(icon_path), exist_ok=True)
        img.save(icon_path)
        logger.info(f"创建默认图标: {icon_path}")

    # 加载图标图像
    image = Image.open(icon_path)

    # 退出应用的回调函数
    def exit_app(icon, item):
        global should_exit
        logger.info("用户请求退出应用")
        should_exit = True
        icon.stop()

        # 如果服务器正在运行，强制结束进程
        if server_running:
            logger.info("强制结束进程")
            os._exit(0)

    # 打开浏览器的回调函数
    def open_app(icon, item):
        webbrowser.open('http://localhost:8000')

    # 创建系统托盘图标
    menu = pystray.Menu(
        pystray.MenuItem("打开界面", open_app),
        pystray.MenuItem("退出", exit_app)
    )

    icon = pystray.Icon("social_media_monitor", image, "社交媒体监控", menu)
    logger.info("系统托盘图标已创建")

    # 运行托盘图标
    icon.run()
    logger.info("系统托盘图标已停止")


if __name__ == "__main__":
    logger.info("启动社交媒体监控系统...")

    # 启动系统托盘图标（在新线程中）
    tray_thread = threading.Thread(target=create_tray_icon, daemon=False)
    tray_thread.start()
    logger.info("系统托盘线程已启动")

    # 自动打开浏览器
    threading.Thread(target=open_browser, daemon=True).start()

    # 检查是否应该退出的线程
    def check_exit():
        global should_exit, server_running
        while not should_exit:
            time.sleep(1)

        if server_running:
            logger.info("收到退出信号，正在关闭服务器...")
            os._exit(0)


    exit_thread = threading.Thread(target=check_exit, daemon=True)
    exit_thread.start()

    # 配置Hypercorn
    config = Config()
    config.bind = ["0.0.0.0:8000"]

    # 标记服务器正在运行
    server_running = True

    try:
        # 运行应用
        asyncio.run(serve(app, config))
    except KeyboardInterrupt:
        logger.info("收到键盘中断，正在关闭服务器...")
    except Exception as e:
        logger.error(f"服务器运行错误: {str(e)}")
    finally:
        server_running = False
        logger.info("服务器已关闭")

        # 如果托盘图标线程还在运行，等待它结束
        if tray_thread.is_alive():
            should_exit = True
            tray_thread.join(timeout=3)
